/******************************************************************************
 * Copyright 2022 The Untouch Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/calibration/lidar_imu_calibrator/include/record_data_dialog.h"

#include <QCloseEvent>
#include <QDateTime>
#include <QFileDialog>
#include <QMessageBox>

#include "ui_record_data_dialog.h"

#include "cyber/common/log.h"
#include "cyber/service_discovery/topology_manager.h"

RecordDataDialog::RecordDataDialog(QWidget *parent)
    : QDialog(parent),
      ui(new Ui::RecordDataDialog),
      start_flag_(false),
      record_data_(new RecordData()) {
  ui->setupUi(this);
  this->setFixedSize(this->size());
  setWindowFlags(windowFlags() & ~Qt::WindowMinMaxButtonsHint);
  EnableControls(true);
  item_mode_ = std::make_shared<QStandardItemModel>();
  ui->lsLidarTopic->setModel(item_mode_.get());
  ui->txtCacheFolder->setText(
      QString("/apollo/data/bag/") +
      QDateTime::currentDateTime().toString("yyyyMMddhhmmss"));
}

RecordDataDialog::~RecordDataDialog() { delete ui; }

void RecordDataDialog::closeEvent(QCloseEvent *event) {
  if (start_flag_) {
    if (QMessageBox::question(
            this, QStringLiteral("Prompt"),
            QStringLiteral("Are you sure you want to exit the record data?"),
            QMessageBox::Yes | QMessageBox::No,
            QMessageBox::No) == QMessageBox::No) {
      event->ignore();
      return;
    }
    Stop();
  }
  event->accept();
}

void RecordDataDialog::on_btnOdometryTopicRefresh_clicked() {
  this->ui->cbOdometryTopic->clear();
  auto topology = apollo::cyber::service_discovery::TopologyManager::Instance();
  auto channel_manager = topology->channel_manager();
  std::vector<std::string> channels;
  channel_manager->GetChannelNames(&channels);
  for (auto &name : channels) {
    if (name.find("odometry") != std::string::npos) {
      this->ui->cbOdometryTopic->addItem(QString::fromStdString(name));
    }
  }
}

void RecordDataDialog::on_btnLidarTopicRefresh_clicked() {
  item_mode_->clear();
  auto topology = apollo::cyber::service_discovery::TopologyManager::Instance();
  auto channel_manager = topology->channel_manager();
  std::vector<std::string> channels;
  channel_manager->GetChannelNames(&channels);
  for (auto &name : channels) {
    if (name.find("PointCloud2") != std::string::npos) {
      QStandardItem *item = new QStandardItem;
      item->setText(QString::fromStdString(name));
      item->setCheckable(true);
      item_mode_->appendRow(item);
    }
  }
}

void RecordDataDialog::on_btnCacheFolderBrowser_clicked() {
  QString dir_name = QFileDialog::getExistingDirectory(
      this, QString("Cache Folder"), "/apollo/data/bag");
  if (!dir_name.isEmpty()) {
    this->ui->txtCacheFolder->setText(dir_name);
  }
}

void RecordDataDialog::on_btnStart_clicked() {
  if (start_flag_) {
    Stop();
  } else {
    Start();
  }
}

void RecordDataDialog::on_btnExit_clicked() { close(); }

void RecordDataDialog::Start() {
  if (!IsInputValid()) {
    return;
  }
  record_data_->SetOdometryTopic(odometry_topic_.toStdString());
  record_data_->SetLidarTopics(lidar_topics_);
  record_data_->SetCacheFolderPath(cache_folder_path_.toStdString());

  if (!record_data_->Start()) {
    QMessageBox::warning(this, QStringLiteral("Prompt"),
                         QStringLiteral("Failed to start record data!"));
    return;
  }
  EnableControls(false);
  this->ui->btnStart->setText("Stop");
  start_flag_ = true;
}

void RecordDataDialog::Stop() {
  record_data_->Stop();
  this->ui->btnStart->setText("Start");
  EnableControls(true);
  start_flag_ = false;
}

void RecordDataDialog::EnableControls(bool enable) {
  this->ui->cbOdometryTopic->setEditable(enable);
  this->ui->btnOdometryTopicRefresh->setEnabled(enable);
  this->ui->lsLidarTopic->setEnabled(enable);
  this->ui->btnLidarTopicRefresh->setEnabled(enable);
  this->ui->txtCacheFolder->setEnabled(enable);
  this->ui->btnCacheFolderBrowser->setEnabled(enable);
  this->ui->progressBar->setVisible(!enable);
}

bool RecordDataDialog::IsInputValid() {
  odometry_topic_ = this->ui->cbOdometryTopic->currentText();
  if (odometry_topic_.isEmpty()) {
    QMessageBox::warning(
        this, QStringLiteral("Prompt"),
        QStringLiteral("Odometry Topic is empty, please select!"));
    return false;
  }

  lidar_topics_.clear();
  for (int i = 0; i < item_mode_->rowCount(); ++i) {
    QStandardItem *item = item_mode_->item(i);
    if (item->checkState() == Qt::Checked) {
      lidar_topics_.push_back(item->text().toStdString());
    }
  }

  if (lidar_topics_.empty()) {
    QMessageBox::warning(
        this, QStringLiteral("Prompt"),
        QStringLiteral("Lidar Topic is empty, please select!"));
    return false;
  }

  cache_folder_path_ = this->ui->txtCacheFolder->text();
  if (cache_folder_path_.isEmpty()) {
    QMessageBox::warning(
        this, QStringLiteral("Prompt"),
        QStringLiteral("Cache folder is empty, please select!"));
    return false;
  }
  return true;
}
